{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "-"
    }
   },
   "source": [
    "# 汇聚层\n",
    "\n",
    "实现汇聚层的前向传播"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import sys\n",
    "sys.path.append('..')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "origin_pos": 3,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [],
   "source": [
    "from d2l import mindspore as d2l\n",
    "from mindspore import nn, ops\n",
    "\n",
    "def pool2d(X, pool_size, mode='max'):\n",
    "    p_h, p_w = pool_size\n",
    "    Y = d2l.zeros((X.shape[0] - p_h + 1, X.shape[1] - p_w + 1))\n",
    "    for i in range(Y.shape[0]):\n",
    "        for j in range(Y.shape[1]):\n",
    "            if mode == 'max':\n",
    "                Y[i, j] = X[i: i + p_h, j: j + p_w].max()\n",
    "            elif mode == 'avg':\n",
    "                Y[i, j] = X[i: i + p_h, j: j + p_w].mean()\n",
    "    return Y"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "验证二维最大汇聚层的输出"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "origin_pos": 6,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] KERNEL(4101928,7f78fa72d740,python):2021-11-08-14:12:16.741.122 [mindspore/ccsrc/backend/kernel_compiler/gpu/gpu_kernel_factory.cc:96] ReducePrecision] Kernel [TensorScatterUpdate] does not support int64, cast input 1 to int32.\n",
      "[WARNING] PRE_ACT(4101928,7f78fa72d740,python):2021-11-08-14:12:16.741.188 [mindspore/ccsrc/backend/optimizer/gpu/reduce_precision_fusion.cc:83] Run] Reduce precision for [TensorScatterUpdate] input 1\n",
      "[WARNING] KERNEL(4101928,7f78fa72d740,python):2021-11-08-14:12:16.745.871 [mindspore/ccsrc/backend/kernel_compiler/gpu/gpu_kernel_factory.cc:96] ReducePrecision] Kernel [TensorScatterUpdate] does not support int64, cast input 1 to int32.\n",
      "[WARNING] PRE_ACT(4101928,7f78fa72d740,python):2021-11-08-14:12:16.745.923 [mindspore/ccsrc/backend/optimizer/gpu/reduce_precision_fusion.cc:83] Run] Reduce precision for [TensorScatterUpdate] input 1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[2, 2], dtype=Float32, value=\n",
       "[[ 4.00000000e+00,  5.00000000e+00],\n",
       " [ 7.00000000e+00,  8.00000000e+00]])"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = d2l.tensor([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]])\n",
    "pool2d(X, (2, 2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "-"
    }
   },
   "source": [
    "验证平均汇聚层"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "origin_pos": 8,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[2, 2], dtype=Float32, value=\n",
       "[[ 2.00000000e+00,  3.00000000e+00],\n",
       " [ 5.00000000e+00,  6.00000000e+00]])"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pool2d(X, (2, 2), 'avg')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "填充和步幅"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "origin_pos": 11,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[1, 1, 4, 4], dtype=Float32, value=\n",
       "[[[[ 0.00000000e+00,  1.00000000e+00,  2.00000000e+00,  3.00000000e+00],\n",
       "   [ 4.00000000e+00,  5.00000000e+00,  6.00000000e+00,  7.00000000e+00],\n",
       "   [ 8.00000000e+00,  9.00000000e+00,  1.00000000e+01,  1.10000000e+01],\n",
       "   [ 1.20000000e+01,  1.30000000e+01,  1.40000000e+01,  1.50000000e+01]]]])"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = d2l.reshape(d2l.arange(16, dtype=d2l.float32), (1, 1, 4, 4))\n",
    "X"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "-"
    }
   },
   "source": [
    "深度学习框架中的步幅与汇聚窗口的大小相同"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "origin_pos": 15,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[1, 1, 1, 1], dtype=Float32, value=\n",
       "[[[[ 1.00000000e+01]]]])"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pool2d = nn.MaxPool2d(3, stride=3)\n",
    "pool2d(X)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "填充和步幅可以手动设定"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "origin_pos": 19,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[1, 1, 2, 2], dtype=Float32, value=\n",
       "[[[[ 5.00000000e+00,  7.00000000e+00],\n",
       "   [ 1.30000000e+01,  1.50000000e+01]]]])"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pool2d = nn.MaxPool2d(3, stride=2)\n",
    "pool2d(ops.Pad(((0,0), (0,0), (1, 1), (1, 1)))(X))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "-"
    }
   },
   "source": [
    "设定一个任意大小的矩形汇聚窗口，并分别设定填充和步幅的高度和宽度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "origin_pos": 25,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[1, 1, 2, 2], dtype=Float32, value=\n",
       "[[[[ 5.00000000e+00,  7.00000000e+00],\n",
       "   [ 1.30000000e+01,  1.50000000e+01]]]])"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pool2d = nn.MaxPool2d((2, 3), stride=(2, 3))\n",
    "pool2d(ops.Pad(((0, 0), (0, 0), (0, 0), (1, 1)))(X))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "slideshow": {
     "slide_type": "slide"
    }
   },
   "source": [
    "汇聚层在每个输入通道上单独运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "origin_pos": 29,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[1, 2, 4, 4], dtype=Float32, value=\n",
       "[[[[ 0.00000000e+00,  1.00000000e+00,  2.00000000e+00,  3.00000000e+00],\n",
       "   [ 4.00000000e+00,  5.00000000e+00,  6.00000000e+00,  7.00000000e+00],\n",
       "   [ 8.00000000e+00,  9.00000000e+00,  1.00000000e+01,  1.10000000e+01],\n",
       "   [ 1.20000000e+01,  1.30000000e+01,  1.40000000e+01,  1.50000000e+01]],\n",
       "  [[ 1.00000000e+00,  2.00000000e+00,  3.00000000e+00,  4.00000000e+00],\n",
       "   [ 5.00000000e+00,  6.00000000e+00,  7.00000000e+00,  8.00000000e+00],\n",
       "   [ 9.00000000e+00,  1.00000000e+01,  1.10000000e+01,  1.20000000e+01],\n",
       "   [ 1.30000000e+01,  1.40000000e+01,  1.50000000e+01,  1.60000000e+01]]]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X = d2l.concat((X, X + 1), 1)\n",
    "X"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "origin_pos": 33,
    "tab": [
     "pytorch"
    ]
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Tensor(shape=[1, 2, 2, 2], dtype=Float32, value=\n",
       "[[[[ 5.00000000e+00,  7.00000000e+00],\n",
       "   [ 1.30000000e+01,  1.50000000e+01]],\n",
       "  [[ 6.00000000e+00,  8.00000000e+00],\n",
       "   [ 1.40000000e+01,  1.60000000e+01]]]])"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pool2d = nn.MaxPool2d(3, stride=2)\n",
    "pool2d(ops.Pad(((0, 0), (0, 0), (1, 1), (1, 1)))(X))"
   ]
  }
 ],
 "metadata": {
  "celltoolbar": "Slideshow",
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.5"
  },
  "rise": {
   "autolaunch": true,
   "enable_chalkboard": true,
   "overlay": "<div class='my-top-right'><img height=80px src='http://d2l.ai/_static/logo-with-text.png'/></div><div class='my-top-left'></div>",
   "scroll": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
